using System;
using System.Collections.Generic;
using System.Threading;
using ComponentSystem;
using Cysharp.Threading.Tasks;
using UnityEngine;
using YooAssetsSystem;

namespace ZYFramework.AudioSystem
{
    /// <summary>
    /// 音频资源管理组件
    /// </summary>
    public class Com_AudioResourceManager : ComponentWithId
    {
        /// <summary>
        /// 资源缓存字典
        /// </summary>
        private readonly Dictionary<string, AudioClip> _audioClipCache = new Dictionary<string, AudioClip>();

        /// <summary>
        /// 资源缓存时间戳字典（用于超时卸载）
        /// </summary>
        private readonly Dictionary<string, float> _cacheTimestamps = new Dictionary<string, float>();

        /// <summary>
        /// 框架配置
        /// </summary>
        private AudioConfig _config;

        /// <summary>
        /// 取消令牌源
        /// </summary>
        private CancellationTokenSource _cancellationTokenSource;

        protected override void Awake()
        {
            base.Awake();
            _cancellationTokenSource = new CancellationTokenSource();
        }

        protected override void Start()
        {
            base.Start();
        }

        /// <summary>
        /// 初始化资源管理器
        /// </summary>
        /// <param name="config">框架配置</param>
        public void Initialize(AudioConfig config)
        {
            this._config = config;

            // 启动资源缓存清理协程
            if (_config != null && _config.ResourceCacheTime > 0)
            {
                UnloadExpiredResourcesAsync(_cancellationTokenSource.Token).Forget();
            }
        }

        /// <summary>
        /// 预加载单个音效资源
        /// </summary>
        /// <param name="audioName">音效名称</param>
        /// <param name="audioType">音频类型</param>
        /// <param name="ct">取消令牌</param>
        /// <returns>是否加载成功</returns>
        public async UniTask<bool> PreloadAudioAsync(string audioName, AudioType audioType, CancellationToken ct = default)
        {
            if (string.IsNullOrEmpty(audioName))
            {
                Debug.LogError("[AudioResourceManager] 音效名称为空");
                return false;
            }

            // 如果已经在缓存中，直接返回
            if (_audioClipCache.ContainsKey(audioName))
            {
                return true;
            }

            try
            {
                string assetPath = GetAssetPath(audioName, audioType);
                AudioClip audioClip = await YAService_Entity.Instance.LoadAudioClip_Async(assetPath, _config.ResourcePackageName);

                if (audioClip != null)
                {
                    _audioClipCache[audioName] = audioClip;
                    _cacheTimestamps[audioName] = Time.time;
                    return true;
                }
                else
                {
                    Debug.LogError($"[AudioResourceManager] 加载音频失败: {assetPath}");
                    return false;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"[AudioResourceManager] 预加载音频异常: {audioName}, 错误: {e.Message}");
                return false;
            }
        }

        /// <summary>
        /// 批量预加载音效资源
        /// </summary>
        /// <param name="audioNames">音效名称列表</param>
        /// <param name="audioType">音频类型</param>
        /// <param name="ct">取消令牌</param>
        /// <returns>成功加载的数量</returns>
        public async UniTask<int> PreloadAudiosAsync(List<string> audioNames, AudioType audioType, CancellationToken ct = default)
        {
            if (audioNames == null || audioNames.Count == 0)
            {
                return 0;
            }

            int successCount = 0;
            foreach (var audioName in audioNames)
            {
                if (ct.IsCancellationRequested)
                {
                    break;
                }

                if (await PreloadAudioAsync(audioName, audioType, ct))
                {
                    successCount++;
                }
            }

            return successCount;
        }

        /// <summary>
        /// 获取音效资源（优先从缓存取，无则加载）
        /// </summary>
        /// <param name="audioName">音效名称</param>
        /// <param name="audioType">音频类型</param>
        /// <param name="ct">取消令牌</param>
        /// <returns>AudioClip资源</returns>
        public async UniTask<AudioClip> GetAudioClipAsync(string audioName, AudioType audioType, CancellationToken ct = default)
        {
            if (string.IsNullOrEmpty(audioName))
            {
                Debug.LogError("[AudioResourceManager] 音效名称为空");
                return null;
            }

            // 优先从缓存获取
            if (_audioClipCache.TryGetValue(audioName, out AudioClip cachedClip))
            {
                _cacheTimestamps[audioName] = Time.time; // 更新使用时间
                return cachedClip;
            }

            // 缓存中没有，异步加载
            try
            {
                string assetPath = GetAssetPath(audioName, audioType);
                Debug.Log($"[AudioResourceManager] 加载音频: {assetPath}");
                AudioClip audioClip = await YAService_Entity.Instance.LoadAudioClip_Async(assetPath, _config.ResourcePackageName);

                if (audioClip != null)
                {
                    _audioClipCache[audioName] = audioClip;
                    _cacheTimestamps[audioName] = Time.time;
                    return audioClip;
                }
                else
                {
                    Debug.LogError($"[AudioResourceManager] 加载音频失败: {assetPath}");
                    return null;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"[AudioResourceManager] 获取音频异常: {audioName}, 错误: {e.Message}");
                return null;
            }
        }

        /// <summary>
        /// 卸载指定音频资源
        /// </summary>
        /// <param name="audioName">音效名称</param>
        public void UnloadAudio(string audioName)
        {
            if (_audioClipCache.TryGetValue(audioName, out AudioClip audioClip))
            {
                _audioClipCache.Remove(audioName);
                _cacheTimestamps.Remove(audioName);

                // 注意：YooAsset的资源释放需要调用对应的Release方法
                // 这里我们只移除缓存引用，实际的资源释放由YooAsset管理
                // 如果需要立即释放，可以通过YooAsset的OperationHandle来管理
            }
        }

        /// <summary>
        /// 卸载所有音频资源
        /// </summary>
        public void UnloadAll()
        {
            _audioClipCache.Clear();
            _cacheTimestamps.Clear();
        }

        /// <summary>
        /// 获取资源路径
        /// </summary>
        /// <param name="audioName">音效名称</param>
        /// <param name="audioType">音频类型</param>
        /// <returns>资源路径</returns>
        private string GetAssetPath(string audioName, AudioType audioType)
        {
            string prefix = audioType == AudioType.BGM ? _config.BGMPathPrefix : _config.SFXPathPrefix;
            return prefix + audioName;
        }

        /// <summary>
        /// 卸载超时未使用的音频资源
        /// </summary>
        private async UniTaskVoid UnloadExpiredResourcesAsync(CancellationToken ct)
        {
            while (!ct.IsCancellationRequested)
            {
                try
                {
                    await UniTask.Delay(TimeSpan.FromSeconds(60f), cancellationToken: ct); // 每分钟检查一次

                    if (_config == null || _config.ResourceCacheTime <= 0)
                    {
                        continue;
                    }

                    float currentTime = Time.time;
                    List<string> expiredKeys = new List<string>();

                    foreach (var kvp in _cacheTimestamps)
                    {
                        if (currentTime - kvp.Value > _config.ResourceCacheTime)
                        {
                            expiredKeys.Add(kvp.Key);
                        }
                    }

                    foreach (var key in expiredKeys)
                    {
                        UnloadAudio(key);
                    }

                    if (expiredKeys.Count > 0)
                    {
                        Debug.Log($"[AudioResourceManager] 卸载了 {expiredKeys.Count} 个超时音频资源");
                    }
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception e)
                {
                    Debug.LogError($"[AudioResourceManager] 卸载超时资源异常: {e.Message}");
                }
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            _cancellationTokenSource?.Cancel();
            _cancellationTokenSource?.Dispose();
            UnloadAll();
        }
    }
}
